package com.warmheart.base.aspect;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.warmheart.base.executor.TraceContext;
import com.warmheart.core.enums.ResultCode;
import com.warmheart.core.ex.base.CoreWhException;
import com.warmheart.core.result.CommonResult;

/**
 * 
 * @ClassName: ApiLogAspect
 * @Description: 业务逻辑日志记录
 * @author ZhangJianyang
 * @date 2025-06-16 09:37:02
 *
 */
@Aspect
@Component
public class ApiLogAspect {

    private static Logger logger = LoggerFactory.getLogger(ApiLogAspect.class);

    @Pointcut("execution(* com.warmheart.controller..*Controller.*(..))")
    public void executeLog() {
    }

    @Around("executeLog()")
    public static Object aroundMethod(ProceedingJoinPoint point) throws Throwable {
        Date startTime = new Date();
        String preSpanId = TraceContext.getSpan();
        TraceContext.setSpan();
        logger.info("----------------------------调用API接口开始----------------------------");
        // 类名称
        String clsName = point.getTarget().getClass().getSimpleName();
        // 执行方法
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        // 方法名称
        String methodName = method.getName();
        // 获取方法返回值类型
        Class<?> cls = null;
        Type type = method.getGenericReturnType();
        if (Class.class.isAssignableFrom(type.getClass())) {
            cls = (Class<?>) type;
        } else if (ParameterizedType.class.isAssignableFrom(type.getClass())) {
            Type rawType = ((ParameterizedType) type).getRawType();
            if (Class.class.isAssignableFrom(rawType.getClass())) {
                cls = (Class<?>) rawType;
            }
        }
        String retClsName = cls.getSimpleName();
        /*
         * 前置通知
         */
        logger.info("调用类：{}, METHOD={}, 方法返回值类型={}", clsName, methodName, retClsName);
        try {
            // 执行目标方法
            return point.proceed();
        } catch (Exception e) {
            // 不同的响应类型进行不同的异常处理，这里可扩展不同类型响应码返回
            if (cls.isAssignableFrom(CommonResult.class)) {
                // 通用返回处理
                if (e instanceof CoreWhException) {
                    // 如果是已处理异常，则输出自定义信息
                    CoreWhException coreWhException = (CoreWhException) e;
                    return CommonResult.failed(coreWhException.getWhEnum(), coreWhException.getMessage());
                } else {
                    // 记录异常
                    logger.error("调用API接口异常：" + e.getMessage(), e);
                    // 输出通用异常信息（服务异常）
                    return CommonResult.failed(ResultCode.ERROR_SERVER);
                }
            } else if (cls.isAssignableFrom(String.class)) {
                // 字符串返回处理
                // 记录异常
                logger.error("调用API接口异常：" + e.getMessage(), e);
                // 输出空字符串
                return StringUtils.EMPTY;
            } else {
                // 记录异常
                logger.error("调用API接口异常：" + e.getMessage(), e);
                // 输出通用异常信息（未知异常）
                return CommonResult.failed(ResultCode.UNKNOWN_SERVER);
            }
        } finally {
            Long nextSpanCost = TraceContext.getSpanCost();
            Date endTime = new Date();
            Long currSpanCost = endTime.getTime() - startTime.getTime() - nextSpanCost;
            logger.info("调用API接口耗时{}ms", currSpanCost);
            /*
             * 返回通知
             */
            logger.info("----------------------------调用API接口结束----------------------------");
            TraceContext.resetSpanCost(endTime.getTime() - startTime.getTime());
            TraceContext.resetSpan(preSpanId);
        }
    }
}
